#include "wdir.h"
#include "ithread.h"
#include <io.h>
#include <shlwapi.h>
#include <direct.h>
#include <fcntl.h>

namespace log4x
{
int
wdir::access(const string& pathname, int mode)
{
    if (
        !(0 == mode ||
          1 == mode ||
          2 == mode ||
          4 == mode ||
          6 == mode))
    {
        return -1;
    }

    if (1 == mode)
    {
        mode = 0;
    }

    if (::access(pathname.c_str(), mode) < 0)
    {
        return -1;
    }
    return 0;
}

int
wdir::copy(const string& src, const string& dst)
{
    int cnt = 0;
    int max = 9;
    while (!CopyFile(src.c_str(), dst.c_str(), false))
    {

        if (cnt++ > max)
            break;

        os::thread()->sleep(100);
    }

    return (cnt > max) ? -1 : 0;
}

void
wdir::copy_dir(const string& src, const string& dst)
{
    SHFILEOPSTRUCT sfo;
    ZeroMemory(&sfo, sizeof(sfo));

    char szSrcDir[MAX_PATH];
    char szDstDir[MAX_PATH];
    strcpy_s(szSrcDir, src.c_str());
    strcpy_s(szDstDir, dst.c_str());
    szSrcDir[strlen(szSrcDir) + 1] = 0;
    szDstDir[strlen(szDstDir) + 1] = 0;

    sfo.wFunc  = FO_COPY;
    sfo.pFrom  = szSrcDir;
    sfo.pTo    = szDstDir;
    sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
    if (0 != SHFileOperation(&sfo))
    {
    }
}

void
wdir::remove(const string& file)
{
    if (is_dir(file))
    {
        char dir[512]      = {0};
        char fileName[512] = {0};

        strcpy(dir, file.c_str());
        strcat(dir, "\\*.*");

        /* 首先查找dir中符合要求的文件 */
        intptr_t hFile;
        _finddata_t fileinfo;

        if ((hFile = _findfirst(dir, &fileinfo)) != -1)
        {
            do
            {
                strcpy(fileName, file.c_str());
                strcat(fileName, "\\");
                strcat(fileName, fileinfo.name);

                /* 检查是不是目录, 如果不是目录,则进行处理文件夹下面的文件 */
                if (!(fileinfo.attrib & _A_SUBDIR))
                {
                    remove(fileName);
                }
                else
                {
                    /* 处理目录, 递归调用 */
                    if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                    {
                        remove(fileName);
                    }
                }
            }
            while (_findnext(hFile, &fileinfo) == 0);

            _findclose(hFile);
            rmdir(file.c_str());
            return;
        }
        return;
    }
    else
    {
        DeleteFile(file.c_str());
    }
}

bool
wdir::is_dir(const string& path)
{
    return PathIsDirectoryA(path.c_str()) ? true : false;
}

int
wdir::mk_dir(const string& path)
{
    string tmp = path;
    if (0 == tmp.length())
    {
        return -1;
    }

    for (std::string::iterator iter = tmp.begin(); iter != tmp.end(); ++iter)
    {
        if (*iter == '\\')
        {
            *iter = '/';
        }
    }
    if (tmp.at(tmp.length() - 1) != '/')
    {
        tmp.append("/");
    }

    std::string::size_type pos = tmp.find('/');
    while (pos != std::string::npos)
    {
        std::string cur = tmp.substr(0, pos - 0);
        if (cur.length() > 0 && !is_dir(cur))
        {
            bool result = false;
            result = CreateDirectoryA(cur.c_str(), NULL) ? true : false;
            if (!result)
            {
                return -1;
            }
        }

        pos = tmp.find('/', pos + 1);
    }

    return 0;
}

int
wdir::ls_dir(const string& path, vector<string>& files)
{
    _finddata_t fd;
    intptr_t handle;

    handle = _findfirst((path + "*.*").c_str(), &fd);
    if (handle < 0)
    {
        return -1;
    }

    while (_findnext(handle, &fd) != -1)
    {
        files.push_back(fd.name);
    }
    _findclose(handle);

    return 0;
}

string
wdir::home(const string& name)
{
    return "c:";
}

string
wdir::absolute_path(const string& relative_path)
{
    char absolute[MAX_PATH] = { 0 };
    if (!_fullpath(absolute, relative_path.c_str(), sizeof(absolute)))
    {
        return "";
    }

    return absolute;
}

int
wdir::stat(const string& path, struct stat& sb)
{
    int fd = ::open(path.c_str(), O_RDONLY);
    if (fd < 0)
    {
        return -1;
    }

    if (fstat(fd, &sb) < 0)
    {
        ::close(fd);
        return -1;
    }
    ::close(fd);
    return 0;
}

int
wdir::chmod(const string& path, uint32_t mode)
{
    return 0;
}
}
